import CommentView from "@/app/[language]/note/components/CommentView"; import useGetComment from "@/app/[language]/note/query/useGetComment"; import usePostToil from "@/app/[language]/note/query/usePostToil"; import w0 from "@/assets/w0.png"; import w1 from "@/assets/w1.png"; import w2 from "@/assets/w2.png"; import w4 from "@/assets/w4.png"; import w5 from "@/assets/w5.png"; import w6 from "@/assets/w6.png"; import w7 from "@/assets/w7.png"; import w8 from "@/assets/w8.png"; import AvatarPlaceText from "@/components/AvatarPlaceText"; import LevelText from "@/components/LevelText"; import { GetNoteAPI } from "@/type/wwwAPI"; import { formatText, getGenreText } from "@/utilities/Utility"; import { useTranslations } from "next-intl"; import Image from "next/image"; import { useState } from "react"; import { Placeholder } from "react-bootstrap"; import Collapse from "react-bootstrap/Collapse"; import Col from "react-bootstrap/esm/Col"; import Row from "react-bootstrap/Row"; import Spinner from "react-bootstrap/Spinner"; import Stack from "react-bootstrap/Stack"; import { Item, Menu, useContextMenu } from "react-contexify"; import Swal from "sweetalert2"; const ws = [w0, w1, w2, "", w4, w5, w6, w7, w8]; export default function NoteView({ noteID, artist, title, genre, levelText, level, topCount, totalCount, fittedText, wantAvatarID, wantAvatarName, handled, }: GetNoteAPI["notes"][number] & { fittedText?: string; wantAvatarID?: string; wantAvatarName?: string; handled?: number; }) { const t = useTranslations(); const [isCommentOpened, setCommentOpened] = useState(false); const { show: viewToilInput } = useContextMenu({ id: `toil-${noteID}`, }); const { mutateAsync: postToil } = usePostToil(); const { data: { comments, commentPlace, totalComments }, isFetched: isCommentLoaded, } = useGetComment(noteID, isCommentOpened, wantAvatarID); return ( <> <Stack gap={2}> <Row className="route flex-nowrap" onClick={() => { setCommentOpened((prevState) => !prevState); }} onContextMenu={(event) => { event.preventDefault(); viewToilInput({ event, props: { noteID } }); }} > <Col className="cc"> <Stack gap={2}> <Stack gap={2} direction="horizontal"> <LevelText level={level} levelText={levelText} className="ellipsis" /> <span className="ellipsis">{title}</span> {isCommentOpened && !isCommentLoaded && <Spinner size="sm" />} </Stack> <Stack gap={2} direction="horizontal"> <span className="ellipsis artist">{artist}</span> <span className="ellipsis genre">{getGenreText(genre)}</span> </Stack> {typeof topCount === "number" && ( <span className="ellipsis fittedText"> {t("topCountText", { topCount: formatText(topCount), })} </span> )} {typeof totalCount === "number" && ( <span className="ellipsis fittedText"> {t("totalCountText", { totalCount: formatText(totalCount), })} </span> )} {fittedText && ( <span className="ellipsis fittedText">{fittedText}</span> )} </Stack> </Col> {typeof handled === "number" && ( <Col xs="auto"> <Image src={ws[handled]} width={10} height={60} alt="" /> </Col> )} </Row> <Row> <Collapse in={isCommentOpened}> <Stack gap={2}> {commentPlace !== -1 && ( <AvatarPlaceText avatarPlace={commentPlace + 1} avatarCount={totalComments} /> )} {comments.map( ({ date, avatarID, avatarName, stand, band, point, commentary, isBand1, judgmentMode, hitPointsMode, isPaused, handled, }) => ( <CommentView key={avatarID} date={date} avatarID={avatarID} avatarName={avatarName} stand={stand} band={band} point={point} isBand1={isBand1} commentary={commentary} isTargetAvatar={ !!(wantAvatarID && wantAvatarID === avatarID) || !!(wantAvatarName && wantAvatarName === avatarName) } judgmentMode={judgmentMode} hitPointsMode={hitPointsMode} isPaused={isPaused} handled={handled} /> ), )} </Stack> </Collapse> </Row> </Stack> <Menu id={`toil-${noteID}`}> <Item onClick={async ({ props: { noteID } }) => { const { isConfirmed, value } = await Swal.fire({ title: t("toilNoteFileText"), input: "text", }); if (isConfirmed) { await postToil({ noteID, commentary: value }); } }} > {t("toilNoteFile")} </Item> </Menu> </> ); } export const NoteViewLoading = () => { return ( <Stack gap={2}> <Placeholder xs={12} size="lg" bg="secondary" animation="wave" /> <Placeholder xs={6} size="lg" bg="secondary" animation="wave" /> </Stack> ); };